`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Yu Zihao
// 
// Create Date: 2021/08/02 12:32:43
// Design Name: 
// Module Name: datapath
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision: V1.0
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module datapath(datapath_in, writenum, write, readnum, clk,vsel, asel, bsel, shift,
                 ALUop, loada, loadb, loadc, loads, datapath_out, Z_out);
  input [15:0] datapath_in;
  input vsel, write,clk, asel, bsel;
  input [2:0] writenum, readnum;
  input [1:0] ALUop, shift;
  input loada,loadb,loadc,loads;
  output [15:0] datapath_out;
  output Z_out;
  
  wire [15:0] data_in;
  assign data_in = vsel ? datapath_in : datapath_out;
  
  //regfile
  wire [15:0] data_out;
  regfile regfile_U0(
    .data_in(data_in),
    .writenum(writenum),
    .write(write),
    .readnum(readnum),
    .clk(clk),
    .data_out(data_out)
  );
  
  reg [15:0] A, B, C;
  reg status;
  assign in = B;
  assign Z_out = status;
  assign datapath_out = C;
  always @(posedge clk)begin
    A <= loada ? data_out : A;
    B <= loadb ? data_out : B;
    C <= loadc ? out : C;
    status <= loads ? Z : status;
  end
  
  //Shifter
  wire [15:0] in, sout;
  shifter shifter_U1(
    .in(in),
    .shift(shift),
    .sout(sout)
  );
  
  assign Ain = asel ? 16'b0 : A;
  assign Bin = bsel ? {11'b0, datapath_in[4:0]} : sout;
  
  //ALU
  wire [15:0] Ain, Bin, out;
  wire Z;
  ALU alu_U2(
    .Ain(Ain),
    .Bin(Bin),
    .ALUop(ALUop),
    .out(out),
    .Z(Z)
  );
endmodule
